#pragma GCC optimize(2)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <unordered_map>
#include <vector>
#include <set>
#include <queue>
#include <numeric>

using namespace std;
using LL = long long;
using PII = pair<int, int>;

int n, m;

int main(){
#ifdef LOCALFLAG
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif


    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n >> m;
    vector<vector<int>> g(n + 1, vector<int>(m + 1));
    vector<int> in(n * m + m);

    //判断每一行是否满足要求 O(mn)
    vector<PII> ft;
    for(int i = 1; i <= n; i ++){
        int mi = 100000000, mx = 0;
        for(int j = 1; j <= m; j ++){
            cin >> g[i][j];

            if(g[i][j] > 0){
                mi = min(g[i][j], mi);
                mx = max(g[i][j], mx);
            }
        }

        if(mx > 0) ft.push_back({mi, mx});
    }

    sort(ft.begin(), ft.end());
    for(int i = 0; i + 1 < ft.size(); i ++){
        if(ft[i].second > ft[i + 1].first){
            cout << "No" << '\n';
            exit(0);
        }
    }

    


    

    int ck = m;
    vector<vector<int>> e(n * m + m);
    vector<int> mp(n * m + 1);

    for(int i = 1; i <= n; i ++){
        //建虚点
        int tmp = ck;
        for(int j = 1; j <= m; j ++){
            if(g[i][j] == 0) continue;
            if(mp[g[i][j]] <= tmp) mp[g[i][j]] = ++ck;
            e[mp[g[i][j]]].push_back(j);
        }


        //对每一行进行排序 O(mnlogmn)
        vector<int> c(m);
        iota(c.begin(), c.end(), 1);
        sort(c.begin(), c.end(), [&](int p1, int p2){
            return g[i][p1] < g[i][p2];
        });

     
        for(int j = 0; j + 1 < m; j ++){
            if(g[i][c[j]] == 0) continue;
            if(g[i][c[j]] < g[i][c[j + 1]]){
                int u = mp[g[i][c[j + 1]]];
                for(int k = j; k >= 0 && g[i][c[k]] == g[i][c[j]]; k --){
                    e[c[k]].push_back(u);
                }
            }
        }
    }

    for(int i = 1; i <= ck; i ++){
        for(auto j: e[i]) in[j] ++;
    }

    queue<int> q;
    int cnt = 0;
    for(int i = 1; i <= ck; i ++){
        if(in[i] == 0) q.push(i);
    }


    while(q.size()){
        cnt ++;
        int u = q.front();
        q.pop();
        for(auto v : e[u]){
            in[v] --;
            if(!in[v]) q.push(v);
        }
    }

  //  cout << cnt << " "<< ck << '\n';
    if(cnt == ck){
        cout << "Yes" << '\n';
    } else{
        cout << "No" << '\n';
    }
    

    return 0;
}